import asyncio

import neo4j


class NeoDriver:
    def __init__(self, url: str, port: int, username: str, passwd: str):
        self.driver = neo4j.GraphDatabase.driver(f"bolt://{url}:{port}", auth=(username, passwd))

        try:
            self.driver.verify_connectivity()
            print(f"Neo4j 版本: {self.driver.execute_query('RETURN 1').summary.server.protocol_version}")
        except neo4j.exceptions.AuthError:
            raise ValueError(f"认证错误!")
        except (BaseException, Exception) as e:
            raise RuntimeError(str(e))

    def close(self):
        self.driver.close()


class AsyncNeoDriver:
    def __init__(self, url: str, port: int, username: str, passwd: str):
        self.driver = neo4j.AsyncGraphDatabase.driver(f"bolt://{url}:{port}", auth=(username, passwd))

    async def verify(self):
        try:
            await self.driver.verify_connectivity()
            result = await self.driver.execute_query('RETURN 1')
            print(f"Neo4j 版本: {result.summary.server.protocol_version}")
        except neo4j.exceptions.AuthError:
            raise ValueError(f"认证错误!")
        except (BaseException, Exception) as e:
            raise RuntimeError(str(e))

    async def close(self):
        await self.driver.close()


class AsyncNeoGitDriver(AsyncNeoDriver):
    async def create_branch_node(self, database: str, repo_name: str, **kwargs):
        async with self.driver.session(database=database) as session:
            await session.execute_write(
                lambda tx: tx.run(f"""
                    MERGE (:{repo_name}:Branch {{name: $name, oid: $oid, remote: $remote}})
                    """, **kwargs)
            )
            print(f"{repo_name}:Branch {kwargs.get('name')} created.")


if __name__ == "__main__":
    d = AsyncNeoDriver("127.0.0.1", 7687, "neo4j", "aixia123!")

    async def _run():
        await d.verify()
        await d.close()

    asyncio.run(_run())
